Add missing mainwin files.
authorrobertl <robertl>
Fri, 31 Jul 2009 17:59:58 +0000 (17:59 +0000)
committerrobertl <robertl>
Fri, 31 Jul 2009 17:59:58 +0000 (17:59 +0000)
gui/mainwindow.cpp [new file with mode: 0644]
gui/mainwindow.h [new file with mode: 0644]
gui/mainwinui.ui [new file with mode: 0644]

diff --git a/gui/mainwindow.cpp b/gui/mainwindow.cpp
new file mode 100644 (file)
index 0000000..beacd80
--- /dev/null
@@ -0,0 +1,997 @@
+// -*- C++ -*-
+// $Id: mainwindow.cpp,v 1.1 2009/07/31 17:59:58 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+#include <QMessageBox>
+#include <QProcess>
+#include <QFileDialog>
+#include <QTextStream>
+#include <QSettings>
+#include <QTemporaryFile>
+
+#include "mainwindow.h"
+#include "babeldata.h"
+#include "appname.h"
+#include "help.h"
+#include "advdlg.h"
+#include "aboutdlg.h"
+#include "optionsdlg.h"
+#include "filterdlg.h"
+#include "processwait.h"
+#include "formatload.h"
+#include "gmapdlg.h"
+#include "upgrade.h"
+
+#ifndef _WIN32
+static const char *deviceNames[] = {
+  "USB:",
+  "/dev/ttyS0",
+  "/dev/ttyS1",
+  "/dev/ttyS2",
+  "/dev/ttyS3",
+  0
+};
+#else
+static const char *deviceNames[] = {
+  "USB:",
+  "COM1:",
+  "COM2:",
+  "COM3:",
+  "COM4:",
+  0
+};
+#endif
+
+const int BabelData::noType = -1;
+const int BabelData::fileType = 0;
+const int BabelData::deviceType = 1;
+//------------------------------------------------------------------------
+static QString findBabelVersion()
+{
+  QProcess babel;
+  babel.start("gpsbabel", QStringList() << "-V");
+  if (!babel.waitForStarted())
+    return QString();
+  babel.closeWriteChannel();
+  if (!babel.waitForFinished())
+    return QString();
+
+  QString str = babel.readAll();
+  str.replace(QRegExp("^[\\s]*"),  "");
+  str.replace(QRegExp("[\\s]+$"),  "");
+  return str;
+}
+//------------------------------------------------------------------------
+static QStringList getCharSets()
+{
+  QProcess babel;
+  babel.start("gpsbabel", QStringList() << "-l");
+  if (!babel.waitForStarted())
+    return QStringList();
+  babel.closeWriteChannel();
+  if (!babel.waitForFinished())
+    return QStringList();
+
+  QStringList strList;
+  QTextStream tstream(babel.readAll());
+  while(!tstream.atEnd()) {
+    QString l = tstream.readLine();
+    if (QRegExp("^\\*").indexIn(l) == 0) {
+      l.replace(QRegExp("^[\\*\\s]*"),  "");
+      l.replace(QRegExp("[\\s]+$"),  "");
+      strList << l;
+    }
+  }
+  return strList;
+}
+
+//------------------------------------------------------------------------
+static QString MakeOptions(const QList<FormatOption>& options) 
+{
+  QString str;
+  for (int i=0; i<options.size(); i++) {
+    if (options[i].getSelected()) {
+      str += ",";
+      str += options[i].getName();
+      if (options[i].getType() != FormatOption::OPTbool) {
+       str += "=" + options[i].getValue().toString();
+      }
+    }
+  }
+  return str;
+}
+
+//------------------------------------------------------------------------
+static QString MakeOptionsNoLeadingComma(const QList<FormatOption>& options) 
+{
+  QString str = MakeOptions(options);
+  return (str.length()) ? str.mid(1) : str;
+    
+}
+//------------------------------------------------------------------------
+MainWindow::MainWindow(QWidget* parent): QMainWindow(parent)
+{
+  loadFormats();
+  ui.setupUi(this);
+  setWindowTitle(appName);
+  babelVersion = findBabelVersion();
+  fmtChgInterlock = false;
+  loadDeviceNameCombos();
+  loadCharSetCombos();
+
+  connect(ui.inputFileOptBtn,        SIGNAL(clicked()), this, SLOT(inputFileOptBtnClicked()));
+  connect(ui.inputDeviceOptBtn,      SIGNAL(clicked()), this, SLOT(inputDeviceOptBtnClicked()));
+  connect(ui.inputFileNameBrowseBtn, SIGNAL(clicked()), this, SLOT(browseInputFile()));
+
+  ui.outputFileOptBtn->setAutoExclusive(false);
+  ui.outputDeviceOptBtn->setAutoExclusive(false);
+  connect(ui.outputFileOptBtn,        SIGNAL(clicked()), this, SLOT(outputFileOptBtnClicked()));
+  connect(ui.outputDeviceOptBtn,      SIGNAL(clicked()), this, SLOT(outputDeviceOptBtnClicked()));
+  connect(ui.outputFileNameBrowseBtn, SIGNAL(clicked()), this, SLOT(browseOutputFile()));
+
+  connect(ui.actionQuit, SIGNAL(triggered()), this, SLOT(closeActionX()));
+  connect(ui.actionHelp, SIGNAL(triggered()), this, SLOT(helpActionX()));
+  connect(ui.actionAbout, SIGNAL(triggered()), this, SLOT(aboutActionX()));
+  connect(ui.actionCheckForUpgrade, SIGNAL(triggered()), this, SLOT(checkForUpgradeX()));
+
+  connect(ui.inputFormatCombo,  SIGNAL(currentIndexChanged(int)),
+         this,                 SLOT(inputFormatChanged(int)));
+  connect(ui.outputFormatCombo, SIGNAL(currentIndexChanged(int)),
+         this,                 SLOT(outputFormatChanged(int)));
+  connect(ui.inputOptionsBtn,   SIGNAL(clicked()),
+         this,                 SLOT(inputOptionButtonClicked()));
+  connect(ui.outputOptionsBtn , SIGNAL(clicked()),
+         this,                 SLOT(outputOptionButtonClicked()));
+  connect(ui.moreOptionButton , SIGNAL(clicked()),
+         this,                 SLOT(moreOptionButtonClicked()));
+
+  connect(ui.buttonBox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(applyActionX()));
+  connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(closeActionX()));
+  connect(ui.xlateFiltersBtn, SIGNAL(clicked()), this, SLOT(filtersClicked()));
+
+  ui.buttonBox->button(QDialogButtonBox::Apply)->setIcon(QIcon(":images/runit.png"));
+  ui.buttonBox->button(QDialogButtonBox::Close)->setIcon(QIcon(":images/exit.png"));
+
+
+  ui.inputOptionsText->setReadOnly(true);
+  ui.outputOptionsText->setReadOnly(true);
+
+  ui.inputFileNameText->setReadOnly(true);
+  ui.outputFileNameText->setReadOnly(true);
+  ui.wayPtLabel->setText("");
+  ui.trackLabel->setText("");
+  ui.routeLabel->setText("");
+  lights[0] = QPixmap::fromImage(QImage(":images/00.png").scaledToHeight(20, Qt::SmoothTransformation));
+  lights[1] = QPixmap::fromImage(QImage(":images/01.png").scaledToHeight(20, Qt::SmoothTransformation));
+  lights[2] = QPixmap::fromImage(QImage(":images/10.png").scaledToHeight(20, Qt::SmoothTransformation));
+  lights[3] = QPixmap::fromImage(QImage(":images/11.png").scaledToHeight(20, Qt::SmoothTransformation));
+  
+  ui.outputWindow->setReadOnly(true);
+
+
+  //--- Restore from registry
+  restoreSettings();
+}
+
+//------------------------------------------------------------------------
+void MainWindow::loadDeviceNameCombos()
+{
+  ui.inputDeviceNameCombo->clear();
+  ui.outputDeviceNameCombo->clear();
+  for (int i=0; deviceNames[i]; i++) {
+    ui.inputDeviceNameCombo->addItem(deviceNames[i]);
+    ui.outputDeviceNameCombo->addItem(deviceNames[i]);
+  }
+}
+//------------------------------------------------------------------------
+void MainWindow::loadCharSetCombos()
+{
+  charSets = getCharSets();
+
+  ui.inputCharSetCombo->clear();
+  ui.outputCharSetCombo->clear();
+  ui.inputCharSetCombo->addItem(tr("default"), QVariant(-1));
+  ui.outputCharSetCombo->addItem(tr("default"), QVariant(-1));
+  for (int i=0; i<charSets.size(); i++) {
+    ui.inputCharSetCombo->addItem(charSets[i], QVariant(i));
+    ui.outputCharSetCombo->addItem(charSets[i], QVariant(i));
+  }
+}
+//------------------------------------------------------------------------
+void MainWindow::checkCharSetCombos()
+{
+  ui.inputCharSetCombo->setEnabled(bd.enableCharSetXform);
+  ui.outputCharSetCombo->setEnabled(bd.enableCharSetXform);
+  ui.inputCharSetCombo->setVisible(bd.enableCharSetXform);
+  ui.outputCharSetCombo->setVisible(bd.enableCharSetXform);
+}
+//------------------------------------------------------------------------
+void MainWindow::inputFileOptBtnClicked()
+{
+  fmtChgInterlock = true;
+  QString fmt = bd.inputFileFormat;
+  ui.inputStackedWidget->setCurrentWidget(ui.inputFilePage);
+  QList<int>indices = inputFileFormatIndices();
+  ui.inputFormatCombo->clear();
+  for (int i=0; i<indices.size(); i++) {
+    int k = indices[i];
+    ui.inputFormatCombo->addItem(formatList[k].getDescription(), QVariant(k));
+  }
+  setComboToFormat(ui.inputFormatCombo, fmt, true);
+  fmtChgInterlock = false;
+}
+
+//------------------------------------------------------------------------
+void MainWindow::inputDeviceOptBtnClicked() 
+{
+  fmtChgInterlock = true;
+  QString fmt = bd.inputDeviceFormat;
+  ui.inputStackedWidget->setCurrentWidget(ui.inputDevicePage);
+  QList<int>indices = inputDeviceFormatIndices();
+  ui.inputFormatCombo->clear();
+  for (int i=0; i<indices.size(); i++) {
+    int k = indices[i];
+    ui.inputFormatCombo->addItem(formatList[k].getDescription(), QVariant(k));
+  }
+  setComboToFormat(ui.inputFormatCombo, fmt, false);
+  fmtChgInterlock = false;
+}
+
+//------------------------------------------------------------------------
+void MainWindow:: outputFileOptBtnClicked()
+{
+  fmtChgInterlock = true;
+  if (ui.outputFileOptBtn->isChecked()) {
+    ui.outputFilePage->setEnabled(true);
+    ui.outputDeviceOptBtn->setChecked(false);
+    QString fmt = bd.outputFileFormat;
+    ui.outputStackedWidget->setCurrentWidget(ui.outputFilePage);
+    QList<int>indices = outputFileFormatIndices();
+    ui.outputFormatCombo->clear();
+    for (int i=0; i<indices.size(); i++) {
+      int k = indices[i];
+      ui.outputFormatCombo->addItem(formatList[k].getDescription(), QVariant(k));
+    }
+    setComboToFormat(ui.outputFormatCombo, fmt, true);
+  } 
+  else {
+    ui.outputStackedWidget->setCurrentWidget(ui.outputFilePage);
+    ui.outputFilePage->setEnabled(false);
+  }
+  fmtChgInterlock = false;
+}
+
+//------------------------------------------------------------------------
+void MainWindow:: outputDeviceOptBtnClicked()
+{
+  fmtChgInterlock = true;
+  if (ui.outputDeviceOptBtn->isChecked()) {
+    ui.outputDevicePage->setEnabled(true);
+    ui.outputFileOptBtn->setChecked(false);
+    QString fmt = bd.outputDeviceFormat;
+    ui.outputStackedWidget->setCurrentWidget(ui.outputDevicePage);
+    QList<int>indices = outputDeviceFormatIndices();
+    ui.outputFormatCombo->clear();
+    for (int i=0; i<indices.size(); i++) {
+      int k = indices[i];
+      ui.outputFormatCombo->addItem(formatList[k].getDescription(), QVariant(k));
+    }
+    setComboToFormat(ui.outputFormatCombo, fmt, false);
+  }
+  else {
+    ui.outputStackedWidget->setCurrentWidget(ui.outputDevicePage);
+    ui.outputDevicePage->setEnabled(false);
+  }
+  fmtChgInterlock = false;
+}
+
+//------------------------------------------------------------------------
+QString MainWindow::filterForFormat(int idx)
+{
+  QString str = formatList[idx].getDescription();
+  str += " (";
+  QStringList extensions = formatList[idx].getExtensions();
+  for (int i=0; i<extensions.size(); i++) {
+    if (i!= 0)
+      str += " ";
+    str += "*." + extensions[i];
+  }
+  str += ");;All Files (*.*)";
+  return str;
+}
+
+//------------------------------------------------------------------------
+bool MainWindow::filterForFormatIncludes(int idx, const QString &fmt)
+{
+  QStringList extensions = formatList[idx].getExtensions();
+  for (int i=0; i<extensions.size(); i++) {
+    if (fmt == extensions[i])
+      return true;
+  }
+  return false;
+}
+
+//------------------------------------------------------------------------
+int MainWindow::currentComboFormatIndex(QComboBox *comboBox)
+{
+  int idx = comboBox->currentIndex();
+  if (idx<0 || idx >= comboBox->count()) {
+    QMessageBox::critical(0, appName,
+                        "*** Internal Error -- current combo index is invalid!");
+    return 0;
+  }
+  return comboBox->itemData(idx).toInt();
+}
+//------------------------------------------------------------------------
+void MainWindow::browseInputFile()
+{
+  QString startFile = bd.inputFileNames.size() ? bd.inputFileNames[0] : bd.inputBrowse;
+  int idx = currentComboFormatIndex(ui.inputFormatCombo);
+  QFileInfo finfo(startFile);
+  if (!finfo.isDir() && (!filterForFormatIncludes(idx, finfo.suffix()))) {
+    startFile = finfo.dir().absolutePath();
+  }
+  QStringList userList = 
+    QFileDialog::getOpenFileNames(0, tr("Select one or more input files"),
+                                 startFile, 
+                                 filterForFormat(idx));
+  if (userList.size()) {
+    bd.inputBrowse = userList[0];
+    bd.inputFileNames = userList;
+    QString str;
+    for (int i=0; i<bd.inputFileNames.size(); i++) {
+      if (i != 0) 
+       str += ", ";
+      str += "\"" + bd.inputFileNames[i] + "\"";
+    }
+    ui.inputFileNameText->setText(str);
+  }
+}
+
+//------------------------------------------------------------------------
+void MainWindow::browseOutputFile()
+{
+  int idx = currentComboFormatIndex(ui.outputFormatCombo);
+  QString startFile = bd.outputFileName.length() == 0 ? bd.outputBrowse : bd.outputFileName;
+  QFileInfo finfo(startFile);
+  if (!finfo.isDir() && (!filterForFormatIncludes(idx, finfo.suffix()))) {
+    startFile = finfo.dir().absolutePath();
+  }
+  QString str =
+    QFileDialog::getSaveFileName(0, tr("Output File Name"),
+                                startFile, 
+                                filterForFormat(idx));
+  if (str.length() != 0) {
+    bd.outputBrowse = str;
+    bd.outputFileName = str;
+    ui.outputFileNameText->setText(str);
+  }
+}
+
+//------------------------------------------------------------------------
+QList<int> MainWindow::inputFileFormatIndices()
+{
+  QList<int>indices;
+  for (int i=0; i<formatList.size(); i++) {
+    if (formatList[i].isReadSomething() && formatList[i].isFileFormat()) 
+      indices<<i;
+  }
+  return indices;
+}
+
+//------------------------------------------------------------------------
+QList<int> MainWindow::inputDeviceFormatIndices()
+{
+  QList<int>indices;
+  for (int i=0; i<formatList.size(); i++) {
+    if (formatList[i].isReadSomething() && formatList[i].isDeviceFormat()) 
+      indices<<i;
+  }
+  return indices;
+}
+
+//------------------------------------------------------------------------
+QList<int> MainWindow::outputFileFormatIndices()
+{
+  QList<int>indices;
+  for (int i=0; i<formatList.size(); i++) {
+    if (formatList[i].isWriteSomething() && formatList[i].isFileFormat()) 
+      indices<<i;
+  }
+  return indices;
+}
+
+//------------------------------------------------------------------------
+QList<int> MainWindow::outputDeviceFormatIndices()
+{
+  QList<int>indices;
+  for (int i=0; i<formatList.size(); i++) {
+    if (formatList[i].isWriteSomething() && formatList[i].isDeviceFormat()) 
+      indices<<i;
+  }
+  return indices;
+}
+
+//------------------------------------------------------------------------
+void MainWindow::loadFormats()
+{
+  if (!FormatLoad().getFormats(formatList)) {
+    QMessageBox::information(0, QString(appName), 
+                            tr("Error reading format configuration.  "
+                               "Check that the backend program \"gpsbabel\" is properly installed "
+                               "and is in the current PATH\n\n"
+                               "This program cannot continue."));
+    exit(1);
+  }
+  if (inputFileFormatIndices().size() == 0 ||
+      inputDeviceFormatIndices().size() == 0 ||
+      outputFileFormatIndices().size() == 0 ||
+      outputDeviceFormatIndices().size() == 0) {
+    QMessageBox::information(0, QString(appName), 
+                            tr("Some file/device formats were not found during initialization.  "
+                               "Check that the backend program \"gpsbabel\" is properly installed "
+                               "and is in the current PATH\n\n"
+                               "This program cannot continue."));
+    exit(1);
+  }
+}
+//------------------------------------------------------------------------
+static int iconIndex(bool a, bool b)
+{
+  return ((a?1:0)*2) + (b?1:0);
+}
+
+//------------------------------------------------------------------------
+void MainWindow::setIndicatorLights(QLabel *label, const QString type, int code) 
+{
+  label->setPixmap(lights[code]);
+  QString s;
+  switch (code) 
+    {
+    default:
+    case 0:
+      s = tr("Input and output formats do not support %1").arg(type);
+      break;
+    case 1:
+      s = tr("Input does not support %1; output format supports %2").arg(type).arg(type);
+      break;
+    case 2:
+      s = tr("Input format supports %1; output format does not support %2").arg(type).arg(type);
+      break;
+    case 3:
+      s = tr("Both input and output formats support %1").arg(type);
+      break;
+    }
+  label->setToolTip(s);
+}
+
+//------------------------------------------------------------------------
+void MainWindow::crossCheckInOutFormats()
+{
+  if (ui.inputFormatCombo->count() == 0 ||
+      ui.outputFormatCombo->count() == 0) {
+    // During format/device switch this is true
+    return;
+  }
+  Format ifmt = formatList[currentComboFormatIndex(ui.inputFormatCombo)];
+  Format ofmt = formatList[currentComboFormatIndex(ui.outputFormatCombo)];
+  
+  ui.xlateWayPtsCk->setEnabled(ifmt.isReadWaypoints() && ofmt.isWriteWaypoints());
+  ui.xlateTracksCk->setEnabled(ifmt.isReadTracks()    && ofmt.isWriteTracks());
+  ui.xlateRoutesCk->setEnabled(ifmt.isReadRoutes()    && ofmt.isWriteRoutes());
+  
+  setIndicatorLights(ui.wayPtLabel, tr("waypoints"), iconIndex(ifmt.isReadWaypoints(), ofmt.isWriteWaypoints()));
+  setIndicatorLights(ui.trackLabel, tr("tracks"), iconIndex(ifmt.isReadTracks(), ofmt.isWriteTracks()));
+  setIndicatorLights(ui.routeLabel, tr("routes"), iconIndex(ifmt.isReadRoutes(), ofmt.isWriteRoutes()));
+}
+
+//------------------------------------------------------------------------
+void MainWindow::displayOptionsText(QLineEdit *le, QComboBox *combo, bool isInput) 
+{
+  int fidx = combo->itemData(combo->currentIndex()).toInt();
+  if (isInput)
+    le->setText(MakeOptionsNoLeadingComma(formatList[fidx].getInputOptions()));
+  else 
+    le->setText(MakeOptionsNoLeadingComma(formatList[fidx].getOutputOptions()));
+
+}
+
+//------------------------------------------------------------------------
+void MainWindow::setComboToFormat(QComboBox *comboBox, const QString &name, bool isFile)
+{
+  int fidx = -1;
+  for (int i=0; i<formatList.size(); i++) {
+    if (formatList[i].getName() == name &&
+       formatList[i].isFileFormat() == isFile) {
+      fidx = i;
+      break;
+    }
+  }
+  if (fidx >=0) {
+    for (int i=0; i<comboBox->count(); i++) {
+      if (comboBox->itemData(i).toInt() == fidx) {
+       comboBox->setCurrentIndex(i);
+       break;
+      }
+    }
+  }
+}
+
+//------------------------------------------------------------------------
+void MainWindow::inputFormatChanged(int comboIdx) 
+{
+  if (fmtChgInterlock)
+    return;
+  int fidx = ui.inputFormatCombo->itemData(comboIdx).toInt();
+  ui.inputOptionsBtn->setEnabled(formatList[fidx].getInputOptions().size()>0);
+  displayOptionsText(ui.inputOptionsText,  ui.inputFormatCombo, true);
+  crossCheckInOutFormats();
+
+  if (ui.inputFileOptBtn->isChecked())
+    bd.inputFileFormat =formatList[fidx].getName();
+  else
+    bd.inputDeviceFormat = formatList[fidx].getName();
+}
+
+//------------------------------------------------------------------------
+void MainWindow::outputFormatChanged(int comboIdx) 
+{
+  if (fmtChgInterlock)
+    return;
+  int fidx = ui.outputFormatCombo->itemData(comboIdx).toInt();
+  ui.outputOptionsBtn->setEnabled(formatList[fidx].getOutputOptions().size()>0);
+  displayOptionsText(ui.outputOptionsText,  ui.outputFormatCombo, false);
+  crossCheckInOutFormats();
+
+  if (ui.outputFileOptBtn->isChecked())
+    bd.outputFileFormat =formatList[fidx].getName();
+  else if (ui.outputDeviceOptBtn->isChecked())
+    bd.outputDeviceFormat = formatList[fidx].getName();
+
+}
+
+//------------------------------------------------------------------------
+void MainWindow::inputOptionButtonClicked() 
+{
+  int fidx = currentComboFormatIndex(ui.inputFormatCombo);
+  OptionsDlg optionDlg(0, 
+                      formatList[fidx].getName(),
+                      formatList[fidx].getInputOptionsRef());
+  optionDlg.setWindowTitle(QString(appName) + " - " + tr("Options for %1").arg(formatList[fidx].getName()));
+  optionDlg.exec();
+  displayOptionsText(ui.inputOptionsText,  ui.inputFormatCombo, true);
+}
+
+//------------------------------------------------------------------------
+void MainWindow::outputOptionButtonClicked() 
+{
+  int fidx = currentComboFormatIndex(ui.outputFormatCombo);
+  OptionsDlg optionDlg(0, formatList[fidx].getName(), formatList[fidx].getOutputOptionsRef());
+  optionDlg.setWindowTitle(QString(appName) + " - " + tr("Options for %1").arg(formatList[fidx].getName()));
+  optionDlg.exec();
+  displayOptionsText(ui.outputOptionsText,  ui.outputFormatCombo, false);
+}
+
+
+//------------------------------------------------------------------------
+bool MainWindow::isOkToGo()
+{
+  if (!((ui.xlateWayPtsCk->isChecked() && ui.xlateWayPtsCk->isEnabled()) ||
+       (ui.xlateRoutesCk->isChecked() && ui.xlateRoutesCk->isEnabled()) ||
+       (ui.xlateTracksCk->isChecked() && ui.xlateTracksCk->isEnabled()))) {
+    QMessageBox::information(0, QString(appName), tr("No valid waypoints/routes/tracks translation specified"));
+    return false;
+  }
+  
+  if ((bd.inputType == BabelData::fileType) &&
+      (bd.inputFileNames.size() == 0)) {
+    QMessageBox::information(0, QString(appName), tr("No input file specified"));
+    return false;
+  }
+
+  if (bd.outputType == BabelData::noType && bd.previewGmap == true) {
+  }
+  if (bd.outputType == BabelData::noType && bd.previewGmap == false) {
+    QMessageBox::information(0, QString(appName), tr("No valid output specified"));
+    return false;
+  }
+  else if (bd.outputType == BabelData::fileType && 
+          bd.outputFileName.length() == 0) {
+    QMessageBox::information(0, QString(appName), tr("No output file specified"));
+    return false;
+  }
+  return true;
+}
+
+//------------------------------------------------------------------------
+bool MainWindow::runGpsbabel(const QStringList &args, QString &errorString, 
+                         QString &outputString)
+{
+  QProcess *proc = new QProcess(0);
+  QString name = "gpsbabel";
+  proc->start(name, args);
+  ProcessWaitDialog *waitDlg = new ProcessWaitDialog(0, proc);
+
+  if (proc->state() == QProcess::NotRunning) {
+    errorString = QString(tr("Process \"%1\" did not start")).arg(name);
+    return false;
+  }
+  
+  waitDlg->show();
+  waitDlg->exec();
+  int exitCode = -1;
+  bool retStatus = false;
+  if (waitDlg->getExitedNormally()) {
+    exitCode = waitDlg->getExitCode();
+    if (exitCode == 0)
+      retStatus = true;
+    else  {
+      errorString = 
+       QString(tr("Process exited unsucessfully with code %1"))
+       .arg(exitCode);
+      retStatus = false;
+    }
+  }
+  else {
+    retStatus = false;
+    errorString = waitDlg->getErrorString();
+  }
+  outputString = waitDlg->getOutputString();
+  delete proc;
+  delete waitDlg;
+  return retStatus;
+}
+
+//------------------------------------------------------------------------
+int MainWindow::formatIndexFromName(bool isFile, const QString &nm)
+{
+  for (int i= 0; i<formatList.size(); i++) {
+    if (nm == formatList[i].getName() && formatList[i].isFileFormat() == isFile)
+      return i;
+  }
+  return 0;
+}
+
+//------------------------------------------------------------------------
+QString MainWindow::charSetFromCombo(QComboBox *combo)
+{
+  int i = combo->itemData((combo->currentIndex())).toInt();
+  return (i >=0 ) ? charSets[i] : QString();
+}
+
+//------------------------------------------------------------------------
+void MainWindow::setComboToCharSet(QComboBox *combo, const QString &cset)
+{
+  for (int i=0; i<charSets.size(); i++) {
+    if (charSets[i] == cset) {
+      combo->setCurrentIndex(i+1); // first index is default;
+    }
+  }
+}
+//------------------------------------------------------------------------
+void MainWindow::applyActionX() 
+{
+  getWidgetValues();
+  if (!isOkToGo())
+    return;
+
+  QStringList args;
+
+  if (bd.debugLevel >=0)     args << QString("-D%1").arg(bd.debugLevel);
+  if (bd.synthShortNames)    args << "-s";
+
+  // Input char set if specified
+  if (bd.enableCharSetXform && bd.inputCharSet != QString()) 
+    args << "-c" << bd.inputCharSet;
+
+  if (bd.xlateWayPts)        args << "-w";
+  if (bd.xlateRoutes)        args << "-r";
+  if (bd.xlateTracks)        args << "-t";
+
+  // Input type, with options
+  bool iisFile = (bd.inputType == BabelData::fileType);
+  int fidx = formatIndexFromName(iisFile, iisFile ?
+                                bd.inputFileFormat : bd.inputDeviceFormat);
+  args << "-i";
+  args << (formatList[fidx].getName() + MakeOptions(formatList[fidx].getInputOptions()));
+  
+  // Input file(s) or device
+  if (bd.inputType == BabelData::fileType) {
+    for (int i=0; i<bd.inputFileNames.size(); i++) 
+      args << "-f" << bd.inputFileNames[i];
+  }
+  else {
+    args << "-f" << bd.inputDeviceName;
+  }
+
+  // --- Filters!
+  args << filterData.getAllFilterStrings();
+
+  // Output char set if specified
+  if (bd.enableCharSetXform && bd.outputCharSet != QString()) 
+    args << "-c" << bd.outputCharSet;
+
+  // Output type, with options
+  if (bd.outputType != BabelData::noType) {
+    bool outIsFile = (bd.outputType == BabelData::fileType);
+    fidx = formatIndexFromName(outIsFile, (outIsFile ?
+                                          bd.outputFileFormat : bd.outputDeviceFormat));
+    args << "-o";
+    args << (formatList[fidx].getName() + MakeOptions(formatList[fidx].getOutputOptions()));
+    
+    // output file or device option
+    if (outIsFile) {
+      if (bd.outputFileName != "")
+       args << "-F" << bd.outputFileName;
+    }
+    else if (bd.outputType == BabelData::deviceType) {
+      args << "-F" << bd.outputDeviceName;
+    }
+  }
+
+  // Now output for preview in google maps
+  QString tempName;
+  if (bd.previewGmap) {
+    QTemporaryFile ftemp;
+    ftemp.open();
+    tempName = ftemp.fileName();
+    ftemp.close();
+
+    // Ideally, expost this in the UI.  For now, just split the track
+    // if we've no recorded fixes for > 5 mins and we've moved > 300 meters.
+    args << "-x";
+    args << "track,pack,sdistance=0.3k,split=5m";
+
+    args << "-o";
+    args << "gpx";
+    args << "-F" << tempName;
+  }
+
+  ui.outputWindow->clear();
+  ui.outputWindow->appendPlainText("gpsbabel " + args.join(" "));
+
+  QString errorString, outputString;
+  QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
+  bool x = runGpsbabel(args, errorString, outputString);
+  QApplication::restoreOverrideCursor();
+
+  ui.outputWindow->appendPlainText(outputString);
+  if (x) {
+    ui.outputWindow->appendPlainText(tr("Translation successful"));
+    if (bd.previewGmap) {
+      this->hide();
+      GMapDialog dlg(0, tempName, bd.debugLevel >=1 ? ui.outputWindow : 0);
+      dlg.show();
+      dlg.exec();
+      this->show();
+    }
+  }
+  else 
+    ui.outputWindow->appendPlainText(tr("Error running gpsbabel: %1\n").arg(errorString));
+}
+
+//------------------------------------------------------------------------
+void MainWindow::closeActionX() 
+{
+  saveSettings();
+  qApp->exit(0);
+}
+
+//------------------------------------------------------------------------
+void MainWindow::closeEvent(QCloseEvent*)  
+{
+  fprintf(stderr, "Close happened\n");
+  closeActionX();
+}
+//------------------------------------------------------------------------
+void MainWindow::setComboToDevice(QComboBox *comboBox, const QString &name)
+{
+  for (int i=0; i<comboBox->count(); i++) {
+    if (comboBox->itemText(i) == name) {
+      comboBox->setCurrentIndex(i);
+      break;
+    }
+  }
+}
+
+//------------------------------------------------------------------------
+void MainWindow::saveSettings()
+{
+  getWidgetValues();
+
+  QSettings settings;
+  bd.saveSettings(settings);
+  for (int i=0; i<formatList.size(); i++) 
+    formatList[i].saveSettings(settings);
+  for (int i=0; i<filterData.filters.size(); i++)
+    filterData.filters[i]->saveSettings(settings);
+}
+
+//------------------------------------------------------------------------
+void MainWindow::restoreSettings()
+{
+  QSettings settings;
+  bd.restoreSettings(settings);
+  for (int i=0; i<formatList.size(); i++) 
+    formatList[i].restoreSettings(settings);
+
+  for (int i=0; i<filterData.filters.size(); i++)
+    filterData.filters[i]->restoreSettings(settings);
+
+  setWidgetValues();
+}
+
+//------------------------------------------------------------------------
+void MainWindow::resetFormatDefaults()
+{
+  int ret = QMessageBox::warning
+    (this, QString(appName),
+     tr("Are you sure you want to reset all format options to default values?"),
+     QMessageBox::Yes | QMessageBox::No);
+  if (ret == QMessageBox::Yes) {
+    for (int i=0; i<formatList.size(); i++) 
+      formatList[i].setToDefault();
+    displayOptionsText(ui.inputOptionsText,  ui.inputFormatCombo, true);
+    displayOptionsText(ui.outputOptionsText,  ui.outputFormatCombo, false);
+  }
+}
+
+//------------------------------------------------------------------------
+void MainWindow::moreOptionButtonClicked()
+{
+  AdvDlg advDlg(0, bd.synthShortNames, 
+               bd.forceGPSTypes, bd.enableCharSetXform, bd.previewGmap, bd.debugLevel);
+  connect(advDlg.formatButton(), SIGNAL(clicked()),
+         this, SLOT(resetFormatDefaults()));
+  advDlg.exec();
+  checkCharSetCombos();
+}
+//------------------------------------------------------------------------
+void MainWindow::aboutActionX()
+{
+  AboutDlg aboutDlg(0, babelVersion, QString(appName) + " Version 0.11");
+  aboutDlg.setWindowTitle(tr("About %1").arg(appName));
+  aboutDlg.exec();
+}
+
+//------------------------------------------------------------------------
+void MainWindow::helpActionX()
+{
+  ShowHelp("gpsbabel.html");
+}
+void MainWindow::checkForUpgradeX()
+{
+  Upgrade *foo = new Upgrade(this);
+  foo->show();
+  foo->checkForUpgrade();
+}
+//------------------------------------------------------------------------
+void MainWindow::filtersClicked()
+{
+  FilterDialog dlg(0, filterData);
+  dlg.runDialog();
+  updateFilterStatus();
+}
+
+
+//------------------------------------------------------------------------
+void MainWindow::updateFilterStatus()
+{
+  bool filterActive = filterData.getAllFilterStrings().size();
+  ui.filterStatus->setEnabled(filterActive);
+  if (filterActive) 
+    ui.filterStatus->setToolTip(tr("One or more data filters are active"));
+  else {
+    ui.filterStatus->setToolTip(tr("No data filters are active"));
+  }
+}
+//------------------------------------------------------------------------
+void MainWindow::setWidgetValues()
+{
+  if (bd.inputType == BabelData::fileType) {
+    ui.inputFileOptBtn->setChecked(true);
+    inputFileOptBtnClicked();
+    setComboToFormat(ui.inputFormatCombo, bd.inputFileFormat, true);
+    ui.inputStackedWidget->setCurrentWidget(ui.inputFilePage);
+  }
+  else {
+    ui.inputDeviceOptBtn->setChecked(true);
+    inputDeviceOptBtnClicked();
+    setComboToFormat(ui.inputFormatCombo, bd.inputDeviceFormat, false);
+    ui.inputStackedWidget->setCurrentWidget(ui.inputDevicePage);
+  }
+  setComboToDevice(ui.inputDeviceNameCombo, bd.inputDeviceName);
+  setComboToCharSet(ui.inputCharSetCombo, bd.inputCharSet);
+
+  if (bd.outputType == BabelData::fileType) {
+    ui.outputFileOptBtn->setChecked(true);
+    outputFileOptBtnClicked();
+    setComboToFormat(ui.outputFormatCombo, bd.outputFileFormat, true);
+    ui.outputStackedWidget->setCurrentWidget(ui.outputFilePage);
+  }
+  else if (bd.outputType == BabelData::deviceType) {
+    ui.outputDeviceOptBtn->setChecked(true);
+    outputDeviceOptBtnClicked();
+    setComboToFormat(ui.outputFormatCombo, bd.outputDeviceFormat, false);
+    ui.outputStackedWidget->setCurrentWidget(ui.outputDevicePage);
+  }
+  else {
+    ui.outputFileOptBtn->setChecked(false);
+    ui.outputDeviceOptBtn->setChecked(false);
+    setComboToFormat(ui.outputFormatCombo, bd.outputFileFormat, true);
+    ui.outputStackedWidget->setCurrentWidget(ui.outputFilePage);
+    ui.outputFilePage->setDisabled(true);
+  }
+
+  setComboToDevice(ui.outputDeviceNameCombo, bd.outputDeviceName);
+  setComboToCharSet(ui.outputCharSetCombo, bd.outputCharSet);
+
+  ui.xlateWayPtsCk->setChecked(bd.xlateWayPts);
+  ui.xlateTracksCk->setChecked(bd.xlateTracks);
+  ui.xlateRoutesCk->setChecked(bd.xlateRoutes);
+
+  crossCheckInOutFormats();
+  displayOptionsText(ui.inputOptionsText,  ui.inputFormatCombo, true);
+  displayOptionsText(ui.outputOptionsText,  ui.outputFormatCombo, false);
+
+  checkCharSetCombos();
+  updateFilterStatus();
+}
+
+//------------------------------------------------------------------------
+void MainWindow::getWidgetValues()
+{
+  int comboIdx = ui.inputFormatCombo->currentIndex();
+  int fidx = ui.inputFormatCombo->itemData(comboIdx).toInt();
+  if (ui.inputFileOptBtn->isChecked()){
+    bd.inputType = BabelData::fileType;
+    bd.inputFileFormat =formatList[fidx].getName();
+  }
+  else {
+    bd.inputType = BabelData::deviceType;
+    bd.inputDeviceFormat =formatList[fidx].getName();
+  }
+  bd.inputDeviceName = ui.inputDeviceNameCombo->currentText();
+  bd.inputCharSet = charSetFromCombo(ui.inputCharSetCombo);
+
+  comboIdx = ui.outputFormatCombo->currentIndex();
+  fidx = ui.outputFormatCombo->itemData(comboIdx).toInt();
+  if (ui.outputFileOptBtn->isChecked()){
+    bd.outputType = BabelData::fileType;
+    bd.outputFileFormat =formatList[fidx].getName();
+  }
+  else if (ui.outputDeviceOptBtn->isChecked()){
+    bd.outputType = BabelData::deviceType;
+    bd.outputDeviceFormat =formatList[fidx].getName();
+  }
+  else {
+    bd.outputType = BabelData::noType;
+  }
+  bd.outputDeviceName = ui.outputDeviceNameCombo->currentText();
+  bd.outputCharSet = charSetFromCombo(ui.outputCharSetCombo);
+
+  bd.xlateWayPts = ui.xlateWayPtsCk->isChecked();
+  bd.xlateTracks = ui.xlateTracksCk->isChecked();
+  bd.xlateRoutes = ui.xlateRoutesCk->isChecked();
+}
+
+
diff --git a/gui/mainwindow.h b/gui/mainwindow.h
new file mode 100644 (file)
index 0000000..31efd66
--- /dev/null
@@ -0,0 +1,104 @@
+// -*- C++ -*-
+// $Id: mainwindow.h,v 1.1 2009/07/31 17:59:58 robertl Exp $
+//------------------------------------------------------------------------
+//
+//  Copyright (C) 2009  S. Khai Mong <khai@mangrai.com>.
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License as
+//  published by the Free Software Foundation; either version 2 of the
+//  License, or (at your option) any later version.
+//
+//  This program is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111
+//  USA
+//
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include "ui_mainwinui.h"
+#include "format.h"
+#include "filterdata.h"
+#include "babeldata.h"
+
+class MainWindow: public QMainWindow {
+  Q_OBJECT
+
+  
+  public:
+  MainWindow(QWidget* parent);
+  QString getBabelVersion(void) {return babelVersion;}
+
+private:
+  Ui_MainWindow     ui;
+  QList<Format>  formatList;
+  QPixmap        lights[4];
+  QStringList    charSets;
+  QString        babelVersion;
+  AllFiltersData filterData;
+  BabelData      bd;
+  bool           fmtChgInterlock;
+
+private:
+  void loadFormats();
+  QString filterForFormat(int idx);
+  bool    filterForFormatIncludes(int idx, const QString &s);
+  int  formatIndexFromName(bool isFile, const QString &);
+  QList<int>inputFileFormatIndices();
+  QList<int>inputDeviceFormatIndices();
+  QList<int>outputFileFormatIndices();
+  QList<int>outputDeviceFormatIndices();
+  int  currentComboFormatIndex(QComboBox *comboBox);
+  bool isOkToGo();
+  bool runGpsbabel(const QStringList &args, QString &errorString, QString &outputString);
+  void crossCheckInOutFormats();
+  void setIndicatorLights(QLabel *label, const QString type, int code) ;
+  void displayOptionsText(QLineEdit *, QComboBox *, bool);
+
+  void saveSettings();
+  void restoreSettings();
+  void setComboToFormat(QComboBox *comboBox, const QString &, bool isFile);
+  void setComboToDevice(QComboBox *comboBox, const QString &);
+
+  void loadDeviceNameCombos();
+  void loadCharSetCombos();
+  void checkCharSetCombos();
+  QString charSetFromCombo(QComboBox *);
+  void setComboToCharSet(QComboBox *, const QString &);
+  void updateFilterStatus();
+  void setWidgetValues();
+  void getWidgetValues();
+
+protected:
+  void closeEvent(QCloseEvent*);
+
+ private slots:
+  void inputFileOptBtnClicked();
+  void inputDeviceOptBtnClicked();
+  void inputOptionButtonClicked();
+  void inputFormatChanged(int);
+  void browseInputFile();
+  void outputFileOptBtnClicked();
+  void outputDeviceOptBtnClicked();
+  void outputOptionButtonClicked();
+  void outputFormatChanged(int);
+  void browseOutputFile();
+  void moreOptionButtonClicked();
+  void applyActionX();
+  void aboutActionX();
+  void helpActionX();
+  void checkForUpgradeX();
+  void closeActionX();
+  void filtersClicked();
+  void resetFormatDefaults();
+
+};
+
+
+#endif
diff --git a/gui/mainwinui.ui b/gui/mainwinui.ui
new file mode 100644 (file)
index 0000000..6204585
--- /dev/null
@@ -0,0 +1,668 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>674</width>
+    <height>582</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MainWindow</string>
+  </property>
+  <widget class="QWidget" name="centralwidget">
+   <layout class="QVBoxLayout" name="verticalLayout_5">
+    <item>
+     <widget class="QGroupBox" name="groupBox">
+      <property name="title">
+       <string>Input </string>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout">
+       <property name="topMargin">
+        <number>4</number>
+       </property>
+       <property name="bottomMargin">
+        <number>4</number>
+       </property>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_5">
+         <item>
+          <widget class="QRadioButton" name="inputFileOptBtn">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="toolTip">
+            <string>If selected, input is from a file.</string>
+           </property>
+           <property name="text">
+            <string>File</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QRadioButton" name="inputDeviceOptBtn">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="toolTip">
+            <string>If selected, input is from a device or GPS unit</string>
+           </property>
+           <property name="text">
+            <string>Device</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <spacer name="horizontalSpacer_2a">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeType">
+            <enum>QSizePolicy::Fixed</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>18</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item>
+          <widget class="QLabel" name="label">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="text">
+            <string>Format</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QComboBox" name="inputFormatCombo">
+           <property name="toolTip">
+            <string>Input data format</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QComboBox" name="inputCharSetCombo">
+           <property name="toolTip">
+            <string>Character encoding of input</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <widget class="QStackedWidget" name="inputStackedWidget">
+         <property name="lineWidth">
+          <number>0</number>
+         </property>
+         <property name="currentIndex">
+          <number>1</number>
+         </property>
+         <widget class="QWidget" name="inputFilePage">
+          <layout class="QHBoxLayout" name="horizontalLayout_4">
+           <property name="margin">
+            <number>0</number>
+           </property>
+           <item>
+            <layout class="QHBoxLayout" name="horizontalLayout_2">
+             <item>
+              <widget class="QPushButton" name="inputFileNameBrowseBtn">
+               <property name="toolTip">
+                <string>Browse for one or more input files. </string>
+               </property>
+               <property name="text">
+                <string>File Name(s)</string>
+               </property>
+               <property name="icon">
+                <iconset resource="app.qrc">
+                 <normaloff>:/images/open.png</normaloff>:/images/open.png</iconset>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QLineEdit" name="inputFileNameText">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                 <horstretch>10</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </item>
+          </layout>
+         </widget>
+         <widget class="QWidget" name="inputDevicePage">
+          <layout class="QVBoxLayout" name="verticalLayout_2">
+           <property name="margin">
+            <number>0</number>
+           </property>
+           <item>
+            <layout class="QHBoxLayout" name="horizontalLayout_3">
+             <item>
+              <widget class="QLabel" name="label_2">
+               <property name="text">
+                <string>Device Name:</string>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QComboBox" name="inputDeviceNameCombo">
+               <property name="toolTip">
+                <string>Name of port to which input device is connected</string>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <spacer name="horizontalSpacer_3a">
+               <property name="orientation">
+                <enum>Qt::Horizontal</enum>
+               </property>
+               <property name="sizeHint" stdset="0">
+                <size>
+                 <width>40</width>
+                 <height>20</height>
+                </size>
+               </property>
+              </spacer>
+             </item>
+            </layout>
+           </item>
+          </layout>
+         </widget>
+        </widget>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_6">
+         <item>
+          <widget class="QPushButton" name="inputOptionsBtn">
+           <property name="toolTip">
+            <string>Options for the selected input format. </string>
+           </property>
+           <property name="text">
+            <string>Options</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="inputOptionsText"/>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item>
+     <widget class="QGroupBox" name="groupBox_2">
+      <property name="title">
+       <string>Translation Options</string>
+      </property>
+      <layout class="QHBoxLayout" name="horizontalLayout_7">
+       <property name="margin">
+        <number>4</number>
+       </property>
+       <item>
+        <widget class="QLabel" name="wayPtLabel">
+         <property name="text">
+          <string>-</string>
+         </property>
+         <property name="scaledContents">
+          <bool>false</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QCheckBox" name="xlateWayPtsCk">
+         <property name="toolTip">
+          <string>If selected, translate waypoints.</string>
+         </property>
+         <property name="text">
+          <string>Waypoints</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="Line" name="line">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer name="horizontalSpacer_6">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeType">
+          <enum>QSizePolicy::Fixed</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>15</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="QLabel" name="routeLabel">
+         <property name="text">
+          <string>-</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QCheckBox" name="xlateRoutesCk">
+         <property name="toolTip">
+          <string>If selected, translate routes.</string>
+         </property>
+         <property name="text">
+          <string>Routes</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="Line" name="line_2">
+         <property name="orientation">
+          <enum>Qt::Vertical</enum>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer name="horizontalSpacer_7">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeType">
+          <enum>QSizePolicy::Fixed</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>15</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="QLabel" name="trackLabel">
+         <property name="text">
+          <string>-</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QCheckBox" name="xlateTracksCk">
+         <property name="toolTip">
+          <string>If selected, translate tracks.</string>
+         </property>
+         <property name="text">
+          <string>Tracks</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer name="horizontalSpacer_4">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeType">
+          <enum>QSizePolicy::Fixed</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>18</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="QLabel" name="filterStatus">
+         <property name="text">
+          <string/>
+         </property>
+         <property name="pixmap">
+          <pixmap resource="app.qrc">:/images/ok20.png</pixmap>
+         </property>
+         <property name="scaledContents">
+          <bool>false</bool>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <widget class="QPushButton" name="xlateFiltersBtn">
+         <property name="toolTip">
+          <string>Data Filters between input and output</string>
+         </property>
+         <property name="text">
+          <string>Filters</string>
+         </property>
+        </widget>
+       </item>
+       <item>
+        <spacer name="horizontalSpacer_8">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>40</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <spacer name="horizontalSpacer_5">
+         <property name="orientation">
+          <enum>Qt::Horizontal</enum>
+         </property>
+         <property name="sizeHint" stdset="0">
+          <size>
+           <width>244</width>
+           <height>20</height>
+          </size>
+         </property>
+        </spacer>
+       </item>
+       <item>
+        <widget class="QPushButton" name="moreOptionButton">
+         <property name="toolTip">
+          <string>More translation options. </string>
+         </property>
+         <property name="text">
+          <string>More Options</string>
+         </property>
+        </widget>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item>
+     <widget class="QGroupBox" name="groupBox_3">
+      <property name="title">
+       <string>Output</string>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout_3">
+       <property name="topMargin">
+        <number>4</number>
+       </property>
+       <property name="bottomMargin">
+        <number>4</number>
+       </property>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_8">
+         <item>
+          <widget class="QRadioButton" name="outputFileOptBtn">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="toolTip">
+            <string>If selected, output is to a file. </string>
+           </property>
+           <property name="text">
+            <string>File</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QRadioButton" name="outputDeviceOptBtn">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="toolTip">
+            <string>If selected, output is to a device or GPS unit</string>
+           </property>
+           <property name="text">
+            <string>Device</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <spacer name="horizontalSpacer_2b">
+           <property name="orientation">
+            <enum>Qt::Horizontal</enum>
+           </property>
+           <property name="sizeType">
+            <enum>QSizePolicy::Fixed</enum>
+           </property>
+           <property name="sizeHint" stdset="0">
+            <size>
+             <width>18</width>
+             <height>20</height>
+            </size>
+           </property>
+          </spacer>
+         </item>
+         <item>
+          <widget class="QLabel" name="label_4">
+           <property name="sizePolicy">
+            <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
+             <horstretch>0</horstretch>
+             <verstretch>0</verstretch>
+            </sizepolicy>
+           </property>
+           <property name="text">
+            <string>Format</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QComboBox" name="outputFormatCombo">
+           <property name="toolTip">
+            <string>Output data format.</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QComboBox" name="outputCharSetCombo">
+           <property name="toolTip">
+            <string>Character encoding of output</string>
+           </property>
+          </widget>
+         </item>
+        </layout>
+       </item>
+       <item>
+        <widget class="QStackedWidget" name="outputStackedWidget">
+         <property name="currentIndex">
+          <number>1</number>
+         </property>
+         <widget class="QWidget" name="outputFilePage">
+          <layout class="QHBoxLayout" name="horizontalLayout_9">
+           <property name="margin">
+            <number>0</number>
+           </property>
+           <item>
+            <layout class="QHBoxLayout" name="horizontalLayout_10">
+             <item>
+              <widget class="QPushButton" name="outputFileNameBrowseBtn">
+               <property name="toolTip">
+                <string>Browse for an output file name. </string>
+               </property>
+               <property name="text">
+                <string>File Name</string>
+               </property>
+               <property name="icon">
+                <iconset resource="app.qrc">
+                 <normaloff>:/images/save.png</normaloff>:/images/save.png</iconset>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QLineEdit" name="outputFileNameText">
+               <property name="sizePolicy">
+                <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
+                 <horstretch>10</horstretch>
+                 <verstretch>0</verstretch>
+                </sizepolicy>
+               </property>
+              </widget>
+             </item>
+            </layout>
+           </item>
+          </layout>
+         </widget>
+         <widget class="QWidget" name="outputDevicePage">
+          <layout class="QVBoxLayout" name="verticalLayout_4">
+           <property name="margin">
+            <number>0</number>
+           </property>
+           <item>
+            <layout class="QHBoxLayout" name="horizontalLayout_11">
+             <item>
+              <widget class="QLabel" name="label_6">
+               <property name="text">
+                <string>Device Name:</string>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <widget class="QComboBox" name="outputDeviceNameCombo">
+               <property name="toolTip">
+                <string>Name of port to which output device is connected</string>
+               </property>
+              </widget>
+             </item>
+             <item>
+              <spacer name="horizontalSpacer_3b">
+               <property name="orientation">
+                <enum>Qt::Horizontal</enum>
+               </property>
+               <property name="sizeHint" stdset="0">
+                <size>
+                 <width>40</width>
+                 <height>20</height>
+                </size>
+               </property>
+              </spacer>
+             </item>
+            </layout>
+           </item>
+          </layout>
+         </widget>
+        </widget>
+       </item>
+       <item>
+        <layout class="QHBoxLayout" name="horizontalLayout_12">
+         <item>
+          <widget class="QPushButton" name="outputOptionsBtn">
+           <property name="toolTip">
+            <string>Options for the selected output format. </string>
+           </property>
+           <property name="text">
+            <string>Options</string>
+           </property>
+          </widget>
+         </item>
+         <item>
+          <widget class="QLineEdit" name="outputOptionsText"/>
+         </item>
+        </layout>
+       </item>
+      </layout>
+     </widget>
+    </item>
+    <item>
+     <widget class="QPlainTextEdit" name="outputWindow">
+      <property name="sizePolicy">
+       <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+        <horstretch>10</horstretch>
+        <verstretch>10</verstretch>
+       </sizepolicy>
+      </property>
+      <property name="toolTip">
+       <string>Output of GPSBabel translation process. </string>
+      </property>
+     </widget>
+    </item>
+    <item>
+     <widget class="QDialogButtonBox" name="buttonBox">
+      <property name="toolTip">
+       <string/>
+      </property>
+      <property name="standardButtons">
+       <set>QDialogButtonBox::Apply|QDialogButtonBox::Close</set>
+      </property>
+     </widget>
+    </item>
+   </layout>
+  </widget>
+  <widget class="QMenuBar" name="menubar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>674</width>
+     <height>22</height>
+    </rect>
+   </property>
+   <widget class="QMenu" name="menuFile">
+    <property name="title">
+     <string>File</string>
+    </property>
+    <addaction name="actionQuit"/>
+   </widget>
+   <widget class="QMenu" name="menuHelp">
+    <property name="title">
+     <string>Help</string>
+    </property>
+    <addaction name="actionHelp"/>
+    <addaction name="separator"/>
+    <addaction name="actionAbout"/>
+    <addaction name="actionCheckForUpgrade"/>
+   </widget>
+   <addaction name="menuFile"/>
+   <addaction name="menuHelp"/>
+  </widget>
+  <widget class="QStatusBar" name="statusbar"/>
+  <action name="actionHelp">
+   <property name="text">
+    <string>GPSBabel Help</string>
+   </property>
+  </action>
+  <action name="actionAbout">
+   <property name="text">
+    <string>About GPSBabel</string>
+   </property>
+  </action>
+  <action name="actionQuit">
+   <property name="text">
+    <string>Quit</string>
+   </property>
+  </action>
+  <action name="actionCheckForUpgrade">
+   <property name="text">
+    <string>Check for Upgrade</string>
+   </property>
+  </action>
+ </widget>
+ <resources>
+  <include location="app.qrc"/>
+ </resources>
+ <connections/>
+</ui>